package com.yyaccp.easybuy.security.controller;

import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.request.OapiSnsGetuserinfoBycodeRequest;
import com.dingtalk.api.response.OapiSnsGetuserinfoBycodeResponse;
import com.taobao.api.ApiException;
import com.yyaccp.easybuy.other.R;
import com.yyaccp.easybuy.security.util.SnsLoginTemplate;
import com.yyaccp.easybuy.security.service.LoginService;
import com.yyaccp.easybuy.security.vo.MockData;
import com.yyaccp.easybuy.security.vo.SnsPlatform;
import com.yyaccp.easybuy.security.vo.SnsUserInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

@Controller
@RequestMapping("/sns")
@Slf4j
public class SnsController {
    @Autowired
    private LoginService loginService;
    /**
     * 前端直接请求该控制器，获取code(授权码)
     * @param platformName 平台名字
     * @param response
     * @throws Exception
     */
    @RequestMapping("/authorize/{platformName}")
    public void authorize(@PathVariable String platformName, HttpServletResponse response) throws Exception {
        SnsPlatform platform = MockData.getSnsPlatform(platformName);
        SnsLoginTemplate socailLogin = new SnsLoginTemplate(platform);
        socailLogin.authorize(response);
    }
    /**
     * 获取授权码成功后，第三方应用自动回调前端页面（在第三方应用中配置的回调地址）
     * 前端页面根据授权码调用/{platformName}/autoLogin控制器
     * /{platformName}/autoLogin控制器根据授权码获取accessToken
     * 根据accessToken获取用户信息
     * 根据用户信息创建token返回给前端
     * 前端在异步回调方法中获取token后设置登录成功并路由
     * @param platformName
     * @param code
     * @param state
     * @return
     * @throws Exception
     */
    @RequestMapping("/{platformName}/snsLogin")
    @ResponseBody
    public R snsLogin(@PathVariable String platformName, String code, String state) throws Exception {
        SnsPlatform platform = MockData.getSnsPlatform(platformName);
        SnsLoginTemplate snsLoginTemplate = new SnsLoginTemplate(platform);
        // 根据code请求accessToken
        String accessToken = snsLoginTemplate.getAccessToken(code, state);
        Assert.hasText(accessToken, "获取accessToken错误");
        // 根据accessToken访问用户信息api或其他api
        Map<String, String> userInfoMap = snsLoginTemplate.getUserInfo(accessToken);
        if (userInfoMap == null) {
            throw new Exception("网络不太通畅，无法获取远程" + platformName + "数据");
        } else {
            return R.ok(loginService.oauth2Login(platformName, new SnsUserInfo(userInfoMap)));
        }
    }

    /**
     * 钉钉账号登录，根据授权码获取简单用户信息和openId等
     * 如需更详细信息请以下参考文档
     * https://www.jianshu.com/p/67b372a441d2
     * https://open.dingtalk.com/document/tutorial/scan-qr-code-to-log-on-to-third-party-websites
     * @param code
     * @param state
     * @return
     * @throws ApiException
     */
    @RequestMapping("/autoLogin/dingtalk")
    @ResponseBody
    public R dingtalkAutoLogin(String code, String state) throws ApiException {
        SnsPlatform platform = MockData.getSnsPlatform("dingtalk");
        DefaultDingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/sns/getuserinfo_bycode");
        OapiSnsGetuserinfoBycodeRequest req = new OapiSnsGetuserinfoBycodeRequest();
        req.setTmpAuthCode(code);
        OapiSnsGetuserinfoBycodeResponse response = client.execute(req, platform.getClientId(), platform.getClientSecret());
        if (log.isDebugEnabled()) {
            log.debug("OapiSnsGetuserinfoBycodeResponse:{}", response.getBody());
        }
        OapiSnsGetuserinfoBycodeResponse.UserInfo userInfo = response.getUserInfo();
        Map<String, String> userInfoMap = new HashMap<>();
        userInfoMap.put("openid", userInfo.getOpenid());
        userInfoMap.put("unionid", userInfo.getUnionid());
        userInfoMap.put("name", userInfo.getNick());
        userInfoMap.put("login", userInfo.getNick());
        userInfoMap.put("id", userInfo.getNick());
        return R.ok(loginService.oauth2Login(platform.getPlatformName(), new SnsUserInfo(userInfoMap)));
    }


}
